package groupon.user.dao.impl;

import groupon.common.dao.impl.GenericDaoImpl;
import groupon.common.util.AppUtil;
import groupon.user.dao.UserDao;
import groupon.user.model.User;
import groupon.user.model.UserSearch;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Repository;

@Repository(value = "userDAO")
public class UserDaoImpl extends GenericDaoImpl<User, Integer> implements UserDao{
	
	final static Log logger = LogFactory.getLog(UserDaoImpl.class);
	
	public boolean delete(Integer id) {
		User user = findUser(id);
		if(user != null){
			delete(user);
			return true;
		}
		logger.info("can'f find user with id: " + id);
		return false;	
	}
	
	public void save(User user) {
		logger.info("--save user with username>>>" + user.getUsername());
		persist(user);
	}

	public List<User> searchAll() {
		logger.info("--get list user>>>");
		return findAll(User.class);
	}
	
	public List<User> findInRange(int firstResult, int maxResults) {
		return findInRange(User.class, firstResult, maxResults); 
	}

	public User update(User user) {
		logger.info("--update user with username >>>" + user.getUsername());
		return merge(user);
	}

	public User findUser(Integer id) {
		logger.info("--find user with id>>>" + id);
		return find(User.class, id);
	}

	@Override
	public User findUserByUsernameOrEmail(String username, String email) {
		List<Predicate> predicates = new ArrayList<Predicate>();
		CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
		CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
		Root<User> from = criteriaQuery.from(User.class);
		criteriaQuery.select(from);
		//check username
		if(!AppUtil.isNullOrEmpty(username)){
			predicates.add(criteriaBuilder.like(from.<String>get(User.PROP_USERNAME), "%" + username + "%"));
		}
		//check email
		if(!AppUtil.isNullOrEmpty(email)){
			predicates.add(criteriaBuilder.equal(from.get(User.PROP_EMAIL), email));
		}
		if(predicates.size() == 1){
			criteriaQuery.where(predicates.get(0));
		}else if(predicates.size() > 1){
			criteriaQuery.where(criteriaBuilder.and(predicates.toArray(new Predicate[0])));
		}
		List<User> listUser = getEntityManager().createQuery(criteriaQuery).getResultList();
		if(!AppUtil.isNullOrEmpty(listUser)){
			return listUser.get(0);
		}
		return null;
	}

	@Override
	public List<User> searchUserInRange(UserSearch userSearch, int firstResult, int maxResults ) {
		List<Predicate> predicates = new ArrayList<Predicate>();
		List<Predicate> predicatRole = new ArrayList<Predicate>();
		CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
		CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
		Root<User> from = criteriaQuery.from(User.class);
		criteriaQuery.select(from);
		//check username
		if(!AppUtil.isNullOrEmpty(userSearch.getUsername())){
			predicates.add(criteriaBuilder.like(from.<String>get(User.PROP_USERNAME), "%" + userSearch.getUsername() + "%"));
		}
		//check email
		if(!AppUtil.isNullOrEmpty(userSearch.getEmail())){
			predicates.add(criteriaBuilder.equal(from.get(User.PROP_EMAIL), userSearch.getEmail()));
		}
		//check create date
		if(!AppUtil.isNullOrEmpty(userSearch.getCreateFrom())){
			predicates.add(criteriaBuilder.greaterThanOrEqualTo(from.<Date>get(User.PROP_CREATED_DATE),AppUtil.convertStringToDate(userSearch.getCreateFrom(),"MM/dd/yyyy")));
		}
		if(!AppUtil.isNullOrEmpty(userSearch.getCreateTo())){
			predicates.add(criteriaBuilder.lessThanOrEqualTo(from.<Date>get(User.PROP_CREATED_DATE),AppUtil.convertStringToDate(userSearch.getCreateTo(),"MM/dd/yyyy")));
		}
		//check user is active
		//predicates.add(criteriaBuilder.isTrue(from.<Boolean>get(User.PROP_ACTIVE)));
		
		//check role
		if(userSearch.isRoleBO()){
			predicatRole.add(criteriaBuilder.equal(from.<String>get(User.PROP_ROLE), User.ACTOR_BO));
		}
		if(userSearch.isRoleFO()){
			predicatRole.add(criteriaBuilder.equal(from.<String>get(User.PROP_ROLE), User.ACTOR_FO));
		}
		if(predicatRole.size() > 1){
			predicates.add(criteriaBuilder.or(predicatRole.toArray(new Predicate[0])));
		}else if(predicatRole.size() == 1){
			predicates.add(predicatRole.get(0));
		}
		//check address
		if(!AppUtil.isNullOrEmpty(userSearch.getStreet())){
			predicates.add(criteriaBuilder.like(from.<String>get(User.PROP_STREET), "%" + userSearch.getStreet() + "%"));
		}
		if(!AppUtil.isNullOrEmpty(userSearch.getCity())){
			predicates.add(criteriaBuilder.like(from.<String>get(User.PROP_CITY), "%" + userSearch.getCity() + "%"));
		}
		if(!AppUtil.isNullOrEmpty(userSearch.getCountry())){
			predicates.add(criteriaBuilder.like(from.<String>get(User.PROP_COUNTRY), "%" + userSearch.getCountry() + "%"));
		}
		if(!AppUtil.isNullOrEmpty(userSearch.getState())){
			predicates.add(criteriaBuilder.like(from.<String>get(User.PROP_STATE), "%" + userSearch.getState() + "%"));
		}
		if(!AppUtil.isNullOrEmpty(userSearch.getTelephone())){
			predicates.add(criteriaBuilder.like(from.<String>get(User.PROP_TELEPHONE), "%" + userSearch.getTelephone() + "%"));
		}
		
		if(predicates.size() == 1){
			criteriaQuery.where(predicates.get(0));
		}else if(predicates.size() > 1){
			criteriaQuery.where(criteriaBuilder.and(predicates.toArray(new Predicate[0])));
		}
		System.out.println(" sql >> :" + criteriaQuery.toString());
		if(firstResult == 0 && maxResults == 0){
			return getEntityManager().createQuery(criteriaQuery).getResultList();	
		}else{
			return getEntityManager().createQuery(criteriaQuery).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
		}
		
	}
	
	

}
